/**
 * <p>文件名:		ProxyServiceImpl.java</p>
 * <p>版权:		CopyrightTag</p>
 * <p>公司:		CompanyTag</p>
 * @author		周华彬(zhouhuabin@sinoiov.com, zhou_hua_bin@163.com)
 */

package com.caits.lbs.framework.services.impl;

import java.lang.reflect.Method;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.logging.log4j.LogManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONArray;
import com.caits.lbs.framework.services.ProxyService;
import com.caits.lbs.framework.utils.BizUtils;



/**
 * <p>
 * ProxyServiceImpl
 * </p>
 * <p>
 * 代理服务实现
 * </p>
 * @author 周华彬(zhouhuabin@sinoiov.com, zhou_hua_bin@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">版本号</th>
 *          <th width="100px">动作</th>
 *          <th width="100px">修改人</th>
 *          <th width="100px">修改时间</th>
 *          </tr>
 *          <!-- 以 Table 方式书写修改历史 -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td>创建类</td>
 *          <td>admin</td>
 *          <td>2018年3月1日 下午5:59:46</td>
 *          </tr>
 *          <tr>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          </tr>
 *          </table>
 */
@Component
@Service("commonProxyService")
public class ProxyServiceImpl implements ProxyService, ApplicationListener<ContextRefreshedEvent> {
	/** 变量:日志记录器,类型:Logger */
	private org.apache.logging.log4j.Logger LOG = LogManager.getLogger(getClass());
	
	private ApplicationContext applicationContext;

	/* (non-Javadoc)
	 * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) */
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if (event.getApplicationContext().getParent() == null) {// root application context 没有parent，他就是老大.
			// 需要执行的逻辑代码，当spring容器初始化完成后就会执行该方法。
			initOtherBizWork(event.getApplicationContext());
		}
	}

	/**
	 * spring初始化完成后 ，再初始化业务工作
	 * @param atx void
	 */
	protected void initOtherBizWork(ApplicationContext atx) {
		applicationContext = atx;
		LOG.info("恭喜spring容器所有实例初始化完毕!");
	}

	/* (non-Javadoc)
	 * @see com.zxr.hyl.excitation.service.ProxyService#invokeService(java.lang.String, java.lang.Object[]) */
	@Override
	public Object invokeService(String beanName, String methodName, Object[] args) {
		Assert.notNull(applicationContext, "spirng容器applicationContext未初始化!");
		Assert.isTrue(applicationContext.containsBean(beanName), "spirng容器中不存在beanName:" + beanName);
		try {
			Object targetService = applicationContext.getBean(beanName);
			Class<?>[] paramTypes = null;
			if (args != null) {
				paramTypes = new Class<?>[args.length];
				for (int index = 0; index < args.length; index++) {
					paramTypes[index] = args[index].getClass();
				}
			}
			Method targetMethod = MethodUtils.getMatchingAccessibleMethod(targetService.getClass(), methodName, paramTypes);
			Assert.notNull(targetMethod, "类" + targetService.getClass().getSimpleName() + "." + methodName + paramTypes + "方法不存在");
			//LOG.info("methodName="+methodName+",参数:"+JSONArray.toJSONString(paramTypes)+",realParam:"+JSONArray.toJSONString(targetMethod.getParameterTypes()));
			Object result = targetMethod.invoke(targetService, args);
			return result;
		} catch (Exception e) {
			BizUtils.printShortException("代理方法调用,beanName:" + beanName + ",methodName:" + methodName, e);
			throw new RuntimeException("代理方法调用异常,beanName:" + beanName + ",methodName:" + methodName);
		}
	}

}
